package storm.Processors;

import java.util.Arrays;
import java.util.Collections;
import java.util.Vector;
import storm.Processors.Cache;

import storm.Tasks.Task;


public class LEATCacheMulti extends Cache {
	Vector <storm.Tasks.Task>Tasks;
	String nameCP ;
	
	int sizeC = 0 ;
	public Task Last_running = null;
	private double Xt;
	private Memory memory;
	
	public void setMemory(int s){
		this.memory = new Memory(s);
	}
	
	
	public LEATCacheMulti (){
		super();
		this.Tasks = new Vector<Task>();
		 nameCP = this.toString()+"_CP";
		// this.cache_Size = new Task[this.getOwnFieldIntValue("Cache_Size")];
	}
	
	
	
	double getXi(Task T){
		double res =0;
		
		//long x = (long)T.getEET() / (long)T.getAET() ;
		int Xi = T.getOwnFieldIntValue("Xi");
		int Li = T.getOwnFieldIntValue("Li");
		double Tpen = Double.parseDouble(this.getOwnFieldStringValue("BurstModeAccesTime"));
	//	res = (Xi/(1-Math.exp(-Li*T.getWCET())  ))  * (1.0-Math.exp(-Li*(double)T.getEET())); ;
		res =  (Xi/(1-Math.exp(-Li*T.getWCET())  ))*(1.0-Math.exp(-Li*(double)T.getEET()/1000*this.Kernel.getprecision())); ;
		String r = T.getOwnFieldStringValue("RWratio");

	  double rw_ratio = Double.valueOf(r);
		res = res *(1+ rw_ratio);
		res = Tpen * res; 
		//res = (Xi / (1-Math.exp(-Li*(T.getWCET())*(1.0-Math.exp((double)-Li*(double)T.getEET()*this.Kernel.precision/1000.0 ));
		//res = (double) (T.getEET()*this.Kernel.precision)/1000; 
		//System.out.println( T.getEET()*this.Kernel.precision + "  x " +  T.getAET()*this.Kernel.precision + "   " + res);
		
		
		return res;
		
	}
	/**
	 * calcul du temps de p?nalit? li? ? la pr?emption en slot temporelle 
	 */
	int getDXi(Task T){
		int res = 0;
	
		return res;
	}
	/*
	 * 
	 * (non-Javadoc)
	 * @see storm.Processors.Cache#havePenality(storm.Tasks.Task)
	 */
	public int havePenality(Task T) {
	
		/**
		 * Marquer une premption cad la t?che pr?cedente est diff?rente de la t?che courante
		 * si everunning est true alors la t?che pred a ?t? pr?empter
		 * 
		 */
		if (this.Last_running != T) {
			if (this.Last_running != null) {
						if (this.Last_running.isEverRunning())
						this.Last_running.setOwnFieldStringValue("preempt", "true");
				
			}
		
			this.Last_running = T;
		}
		/**
		 * Renseigner l'utilisation de la chache
		 */
		
		if (!this.Tasks.contains(T)){
		
			
			this.Tasks.add(T);
			T.setOwnFieldIntValue(this.nameCP,0);
			T.setOwnFieldIntValue(this.nameCP+"Cachesize", 0);
		
		}
		if (T.getET()==0) {
			//	T.setOwnFieldIntValue(this.nameCP, 0);
				//T.setOwnFieldIntValue(this.nameCP+"Cachesize", 0);
			//	this.Last_running.setOwnFieldStringValue("preempt", "false");
				
			}
		/**
		 * 
		 * refilling
		 */
		boolean preempt = Boolean.parseBoolean(T.getOwnFieldStringValue("preempt"));
		if (preempt){
		int Xi = T.getOwnFieldIntValue("Xi");
		int Li = T.getOwnFieldIntValue("Li");
		//int used = T.getOwnFieldIntValue(this.nameCP+"Cachesize");
		double  Xt =  (Xi/(1-Math.exp(-Li*T.getWCET())  ))*(1.0-Math.exp(-Li*(double)T.getEET()/1000*this.Kernel.getprecision())); ;
		//double Xlit=0;
		double Xlit = ( Xi * T.getEET( ) ) / ( T.getWCET ( ) ) ; 
		double DeltaXi = Xt - Xlit;
		
		
	 // Calcul de ceux que je dois demander au cache 
	//	double need =  Xt - used;
		//	if (need < 0 ) need = 0;
			
		//Calcul de ceux que T ? d?ja dans le cache 
		/*int cacheUsed = this.memory.getUsed(T);
		int cacheRequest = (int)need - cacheUsed ;
		if (cacheRequest < 0) cacheRequest=0;
		*/
		
		int cacheUsed = this.memory.getUsed(T);
		int need = (int) (DeltaXi -  cacheUsed);
		if (need < 0 ) need = 0;
		this.memory.addLine(T, (int) need, this.Kernel.getTime());
	//	this.memory.addLine(T, cacheRequest, this.Kernel.getTime());
		System.out.println(this.Kernel.getTime() + "  " + T.getId() + "  " +  (int)Xt + "  " + (int) DeltaXi + " "+ (int)need   + "  " + memory.getCarto());
		T.setOwnFieldIntValue(this.nameCP+"Cachesize", (int) Xt );

		}

		
		/**
		 * Calcul du DeltaXi si la t?che a ?t? preemptre
		 	*/
		/*	boolean preempt = Boolean.parseBoolean(T.getOwnFieldStringValue("preempt"));
			if (preempt){
				/**
				 * Calcul du nombre de defatu de cache n?cessaire au moment de la pr?emmtoin
				 * 
				 */
			
			//	 Xlit = (Xi * T.getEET())  / (T.getWCET());
				
		//	}
			
		
			/**
			 * calcul du Xi comme dans le cas sans pr?emption 
			 * cad que l'on a consomm? les p?nalit? du ? la restauration du cache pour le t?che qui revient 
			 */
			double value =0;
			

			
		
	
		T.setOwnFieldStringValue("preempt", "false");
		return 0;
	}



	private void setXt(double xt) {
		this.Xt = xt;
		// TODO Auto-generated method stub
		
	}

	
}
